<?php
/**
 * class App_Model_User
 *
 * @author kim
 */
class App_Model_User extends App_Model_Abstract
{
    // table name
    protected $_name = 'dine2_user';

    /**
     * update user's favorite foods list
     *
     * @todo to update what really need to be updated
     *
     * @param int $userId
     * @param array $foodIds
     * @return null
     */
    protected function _updateUserFoods($userId, $foodIds)
    {
        $db = $this->getTable()->getAdapter();
        $db->delete('dine2_user_food', $db->quoteInto('user_id = ?', $userId));
        if (!empty($foodIds)) {
            foreach ($foodIds as $fid) {
                $userFoods[] = "(NULL, $userId, $fid)";
            }
            $db->query("INSERT INTO `dine2_user_food` VALUES " . implode(',', $userFoods));
        }
    }

    /**
     * check if user is loged in
     *
     * @return boolean
     */
    static public function isLogedIn()
    {
        $auth = Zend_Auth::getInstance();
        if ($auth->hasIdentity()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * set user password in hash
     *
     * @param string|false $password
     * @return string
     */
    static public function setPassword($password = false)
    {
        if ($password) {
            $result = Zend_Crypt::hash('md5', $password);
        } else {
            $result = Zend_Crypt::hash('md5', time());
        }
        return $result;
    }

    /**
     * get authenticate result
     *
     * @param array $data
     * @return true|string
     */
    public function getLoginResult($data)
    {
        $auth = Zend_Auth::getInstance();
        $adapter = new Zend_Auth_Adapter_DbTable(
            $this->getTable()->getAdapter(),
            $this->_name,
            'email',
            'password',
            'MD5(?) AND is_active != 0'
        );
        $adapter->setIdentity($data['email']);
        $adapter->setCredential($data['password']);
        $result = $auth->authenticate($adapter);

        if ($result->isValid()) {
            return true;
        } else {
            return implode("\n", $result->getMessages());
        }
    }

    /**
     * get register result
     *
     * @todo send email of password, set is_active to 0
     *
     * @param array $data
     * @return true|null
     */
    public function getRegisterResult($data)
    {
        $foodIds = $data['user_food'];
        unset($data['user_food']);

        $data['password'] = self::setPassword();
        $data['created_at'] = $data['modified_at'] = date('Y:m:d h:i:s');

        if ($userId = $this->getTable()->insert($data)) {
            // refresh user favorite foods
            $this->_updateUserFoods($userId, $foodIds);

            return true;
        }
    }

    /**
     * set key for password reset
     *
     * @param string $email
     * @param string $key
     * @return boolean
     */
    public function setPasswordKey($email, $key)
    {
        $result = false;
        $query = "SELECT `email` FROM `dine2_user` WHERE `email` = '$email' AND `is_active` = 1";
        $r = $this->getTable()->getAdapter()->fetchCol($query);
        if (count($r)) {
            if ($this->getTable()->update(array('key' => $key), array('email = ?' => $email))) {
                $result = true;
            }
        }
        return $result;
    }

    /**
     * get reset password result
     *
     * @param array $data
     * @return boolean
     */
    public function getResetPasswordResult($email, $key, $newPassword)
    {
        $result = false;
        if (!empty($key)) {
            $query = "SELECT `email` FROM `dine2_user` WHERE `email` = '$email' AND `key` = '$key' AND `is_active` = 1";
            $r = $this->getTable()->getAdapter()->fetchCol($query);
            if (count($r)) {
                if ($this->getTable()->update(array('key' => '', 'password' => self::setPassword($newPassword)), array('email = ?' => $email))) {
                    $result = true;
                }
            }
        }
        return $result;
    }

    /**
     * do profile update and return update feedback
     *
     * @param array $data
     * @param int $userId
     * @return
     */
    public function getProfileUpdateResult($data)
    {
        // update modified date
        $data['modified_at'] = date('Y:m:d h:i:s');

        $userId = $data['user_id'];
        $foodIds = $data['user_food'];
        unset($data['user_id'], $data['user_food']);

        // refresh user favorite foods
        $this->_updateUserFoods($userId, $foodIds);

        // update user info
        $affectedRows = $this->getTable()->update($data, array('id = ?' => $userId));
        if ($affectedRows) {
            return true;
        }
    }

    /**
     * user logout function
     *
     * @return null
     */
    public function logout()
    {
        Zend_Auth::getInstance()->clearIdentity();
    }

    /**
     * get user favorite food ids by user id
     *
     * @return array
     */
    public function getFoodIdsById($id)
    {
        $db = $this->getTable()->getAdapter();
        $query = "SELECT `food_id` FROM `dine2_user_food` WHERE `user_id` = '$id'";
        $foods = $db->fetchCol($query);
        return $foods;
    }

    /**
     * get users who wrote most reviews
     *
     * @param int $limit
     * @return Zend_Db_Table_Rowset
     */
    public function getTopReviewers($limit = 5)
    {
        $db = $this->getTable()->getAdapter();
        $query = "SELECT `dine2_user`.* FROM `dine2_user` "
               . "WHERE `review_count` > 0 AND `is_active` = 1 ORDER BY `review_count` DESC LIMIT $limit";
        $reviewers = $db->fetchAll($query);
        return $reviewers;
    }

    /**
     * get all users who wrote reviews
     *
     * @return Zend_Db_Table_Rowset
     */
    public function getReviewers()
    {
        $db = $this->getTable()->getAdapter();
        $query = "SELECT `dine2_user`.*, "
               . "`dine2_city`.`name` as city_name "
               . "FROM `dine2_user` LEFT JOIN `dine2_city` ON `dine2_user`.`city_id` = `dine2_city`.`id` "
               . "WHERE `review_count` > 0 AND `is_active` = 1 ORDER BY review_count DESC";
        $reviewers = $db->fetchAll($query);
        return $reviewers;
    }

    /**
     * get user profile by user id or user email
     *
     * @todo may simplify ?
     * @param int|string $identity
     * @return array
     */
    public function getProfile($identity)
    {
        $db = $this->getTable()->getAdapter();
        $query = "SELECT `dine2_user`.*, "
               . "if (`dine2_user`.`birth_date` = '0000-00-00 00:00:00', 'N/A', (YEAR(CURDATE())-YEAR(`dine2_user`.`birth_date`))) as age, "
               . "(CASE `dine2_user`.`gender` WHEN '1' THEN 'Male' WHEN '2' THEN 'Female' ELSE 'Prefer not to say' END) as gender_name, "
               . "`dine2_city`.`name` as city_name, "
               . "`dine2_state`.`code` as state_code "
               . "FROM `dine2_user` "
               . "LEFT JOIN `dine2_city` ON `dine2_user`.`city_id` = `dine2_city`.`id` "
               . "LEFT JOIN `dine2_state` ON `dine2_user`.`state_id` = `dine2_state`.`id` "
               . "WHERE (`dine2_user`.`id` = '$identity' OR `dine2_user`.`email` = '$identity') AND `is_active` = 1 LIMIT 1";
        $user = $db->fetchRow($query);
        return $user;
    }

}
